Date : 19 janvier 1991 ; essai
30 avril 1991 ; mot de passe
11 juin 1991 ; disque clef
26 novembre 1991 ; disque courant
Protection : MOT DE PASSE + DISQUE CLEF
Programme : SAKOBAN II
Outils : PANO_AT + QUAID ANALYSER + SOFT-ICE +
MASM + LINK + EXE2BIN.
Fichier : VGASTART.EXE + FRED2.COM
Temps pass� : Pas mal...
Soci�t� : Soci�t� Japonaise
Divers : PERISCOPE � 1578:0000 +
cr�ation de FRED2.COM, SAKOBAN.EXE,
SAKO.COM
Origine : INDONESIE - SOLO
Num�ro : 066
Le m�me principe de codage de la routine de demande du mot de passe
que MAYONG � l'exception que la routine de codage est en clair...
Voici la boucle de d�codage des octets, cette boucle se trouve
( heureusement ) dans le programme. Dans le cas de MAYONG elle est
elle-m�me cod�e !
35D7:00DD 740C JZ 00EB
35D7:00DF 88E1 MOV CL,AH
35D7:00E1 41 INC CX
35D7:00E2 41 INC CX
35D7:00E3 26 ES:
35D7:00E4 8A01 MOV AL,[BX+DI]
35D7:00E6 AA STOSB
35D7:00E7 E2FA LOOP 00E3
35D7:00E9 EBA6 JMP 0091
Ce saut doit �tre modifi� en JNZ (75) pour que le programme fonctionne
sans mot de passe.
2578:0A98 7403 JZ 0A9D ; no jump
2578:0A9A E97000 JMP 0B0D
2578:0A9D 33C0 XOR AX,AX
Cet octet ( 74 ) est lu en ES:09F2, je dump la chaine...
AX=A801 BX=FF5A CX=0003 DX=0003 SP=007E BP=0005 SI=054D DI=0A98
DS=2969 ES=2578 SS=35F3 CS=35D7 IP=00E3 NV UP EI PL NZ NA PO NC
RD ES:09F2 = 74
35D7:00E3 26 ES:
35D7:00E4 8A01 MOV AL,[BX+DI]
DUMP: mais impossible de la trouver avec PCTOOLS.
Carte PANO sur ES:09F2...
2578:09F2 74 03 E9 0D 00 B8-22 26 50 B8 28 25 50 9A
AX=8874 BX=FFF6 CX=0002 DX=000A SP=007E BP=0221 SI=04F0 DI=09F3
DS=2969 ES=2578 SS=35F3 CS=35D7 IP=00E3 NV UP EI PL NZ NA PE NC
RD ES:09E9 = 03
35D7:00E3 26 ES:
35D7:00E4 8A01 MOV AL,[BX+DI]
Idem: l'octet est lu en ES:9E8...
2578:09E8 74 03 E9 5C 00 83 3E 26
AX=0174 BX=FE37 CX=0002 DX=0006 SP=007E BP=000D SI=04E8 DI=09E9
DS=2969 ES=2578 SS=35F3 CS=35D7 IP=00E3 NV UP EI PL NZ NA PE NC
RD ES:0820 = 03
35D7:00E3 26 ES:
35D7:00E4 8A01 MOV AL,[BX+DI]
Idem, ES:81F
2578:081F 74 t
AX=C074 BX=FFBD CX=0002 DX=000E SP=007E BP=300D SI=03D4 DI=0820
DS=2969 ES=2578 SS=35F3 CS=35D7 IP=00E3 NV UP EI PL NZ NA PE NC
RD ES:07DD = 03
35D7:00E3 26 ES:
35D7:00E4 8A01 MOV AL,[BX+DI]
En ES:7DC cette fois...
2578:07DC 74 03 E9 20
AX=0074 BX=FFBD CX=001F DX=000B SP=007E BP=01A1 SI=03CA DI=07DD
DS=2969 ES=2578 SS=35F3 CS=35D7 IP=00E3 NV UP EI PL NZ AC PO NC
RD ES:079A = 03
35D7:00E3 26 ES:
35D7:00E4 8A01 MOV AL,[BX+DI]
Puis en 799...
2578:0799 74 03 E9 20 00 A1 0C
Et en 383...
2578:0383 74 03 E9 30 01 33 C0
AX=3001 BX=FFFA CX=0000 DX=0008 SP=007E BP=0030 SI=01A3 DI=0383
DS=2969 ES=2578 SS=35F3 CS=35D7 IP=009D NV UP EI PL NZ NA PO CY
RD DS:01A3 = 74 WR ES:0383 = E0
35D7:009D A4 MOVSB
Puis en dernier lieu l'octet est lu en DS:01A3...
2969:01A3 74 E7 30 01 FC-8F AD E9 1F 00 90 8B 1E
Et cette chaine se trouve ( enfin ) dans le programme, mais ce n'est
pas fini. Apr�s avoir modifi� l'octet 74 en 75 et relanc� le programme
on obtient ceci:
DUPLICATE DEFINITION AT LINE 0 IN MODULE VGASTART AT ADRESSE 1997:0048
G�nial ! cet octet est apparement une partie vitale d'un saut que le
programme utilise � cet endroit. Bien jou�...
Le m�me essai est effectu� avec l'octet E9 ( saut inconditionnel ) mais
bien entendu le r�sultat est identique:
MESSAGE: SETUP MAL INITIALISE, etc...
Il ne reste plus qu'� modifier le programme ( s'il se laisse faire...)
Un essai est fait en sautant dans une zone texte. J'ai trouv� un nom:
"Fabrice bellard" a la fin du programme en DS:C800 en fait 2969:C800.
Je transforme la suite:
35D7:00DD 740C JZ 00EB
35D7:00DF 88E1 MOV CL,AH
35D7:00E1 41 INC CX
35D7:00E2 41 INC CX
35D7:00E3 26 ES:
35D7:00E4 8A01 MOV AL,[BX+DI]
35D7:00E6 AA STOSB
35D7:00E7 E2FA LOOP 00E3
35D7:00E9 EBA6 JMP 0091
En...
35D7:00DD 740C JZ 00EB
35D7:00DF EA00C86929 JMP 2969:C800
35D7:00E4 90
35D7:00E5 90
35D7:00E6 90
35D7:00E7 90
35D7:00E8 90
35D7:00E9 EBA6 JMP 0091
Et en 2969:C800 je place:
2969:C800 88E1
2969:C802 41
2969:C803 41
2969:C804 26
2969:C805 8A01
2969:C807 AA
2969:C808 E2FA
2969:C80A EAE900D735 JMP 35D7:00E9
Et devinez quoi: Le programme se plante parcequ'il y a un control de
CRC quelquepart....
MESSAGE: CRC ERROR.
J'abandonne.
TIME PASSES...
Pas longtemps, je d�cide de traquer le test du CRC avec QUAID car
apparement la sortie de la chaine de caract�res se fait avec l'INT 21.
Ici on voit que le contenu de BP et DX est diff�rent. ( il est identique
pour un CRC correct ). Et on saute vers le DOS grace � la sous-fonction
4C de l'INT 21.
Il suffit de forcer le saut pour passer le test du CRC.
AX=00C4 BX=35D7 CX=0000 DX=C408 SP=007E BP=C77A SI=FFFF DI=FFFF
DS=31E6 ES=35D7 SS=35F3 CS=31E6 IP=003D NV DN EI NG NZ NA PO NC
31E6:003D 39D5 CMP BP,DX
31E6:003D 39D5 CMP BP,DX
31E6:003F 740C JZ 004D
31E6:0041 BA9101 MOV DX,0191
31E6:0044 B409 MOV AH,09
31E6:0046 CD21 INT 21
31E6:0048 B8FF4C MOV AX,4CFF
31E6:004B CD21 INT 21
31E6:004D 53 PUSH BX
31E6:004E B85300 MOV AX,0053
31E6:0051 50 PUSH AX
31E6:0052 CB RETF
Modifier le saut JZ en JMP comme suit:
31E6:003D 39D5 CMP BP,DX
31E6:003F EB0C JMP 004D
31E6:0041 BA9101 MOV DX,0191
31E6:0044 B409 MOV AH,09
31E6:0046 CD21 INT 21
31E6:0048 B8FF4C MOV AX,4CFF
31E6:004B CD21 INT 21
31E6:004D 53 PUSH BX
31E6:004E B85300 MOV AX,0053
31E6:0051 50 PUSH AX
31E6:0052 CB RETF
Voil� pour le CRC.
Mais ma routine r�essay�e ne tourne toujours pas; tout se plante.
Je vais essayer de sauter dans le segment courant...
En faisant un SEARCH dans le segment courant je retombe sur mon
*FABRICE BELLARD* qui fait 17 octets de long. Cel� m'�tonnerait
beaucoup que le programme ai besoin de cette chaine.
( je me demande d'ailleurs ce qu'un nom bien fran�ais fait au
milieu de ce logiciel japonais !! ).
L'offset de ce nom se trouve en CS:11F par rapport � ma routine.
Je d�cide d'y sauter et d'en revenir pour voir si le programme tourne
toujours.
C'est OK. A partir de maintenant il faut que je fasse tenir ma routine
personelle dans ces 17 octets....
35D7:00DD 740C JZ 00EB
35D7:00DF EB3E JMP 011F Voici mon saut en 11F....
35D7:00E1 41 INC CX
35D7:00E2 41 INC CX
35D7:00E3 26 ES:
35D7:00E4 8A01 MOV AL,[BX+DI]
35D7:00E6 AA STOSB
35D7:00E7 E2FA LOOP 00E3
35D7:00E9 EBA6 JMP 0091
Et ma routine en 11F;
35D7:011F 88E1 MOV CL,AH
35D7:0121 26 ES:
35D7:0122 803E980A74 CMP BYTE PTR [0A98],74 ; 't'
35D7:0127 75B8 JNZ 00E1
35D7:0129 26 ES:
35D7:012A FE06980A INC BYTE PTR [0A98]
35D7:012E EBB1 JMP 00E1
Qui tient juste en 17 octets, merci FABRICE BELLARD !
Bon. c'est pas tout on essaye le soft maintenant. Et quoi ?
J'obtiens le m�me message
DUPLICATE DEFINITION AT LINE 0 .....
que lorsque j'avais trouv� la position de mon octet 74 et que je
l'avais modifi� en 75.
Aller, au point ou j'en suis je v�rifie quand m�me ma position 0A98
j'y trouve bien 75. Donc ma routine fonctionne. Je vais aller � la
chasse de mon DUPLICATE DEFINITION....
En lan�ant QUAID on s'aper�oit apr�s l'INT 33 ( break off et on ) que
le programme compare l'int�grit� des octets de la zone de la demande du
mot de passe. Interruption n'395 de QUAID.
Le CALL SEG:3AD7 sort le fameux message... ce qui est curieux c'est
qu'apparement la zone de d�codage des dits octets n'est pas test�e
puisqu'un saut et un retour pla�� � cet endroit n'affecte pas le test.
Il faut donc juste apr�s le test �crire 75 � la place de 74. Ceci
avant l'INT 21 sous fonction 19 et apr�s l'INT 21 sous fonction 3301.
A voir...
D�but avril 1991...
Grace � une doc sur les capacit�s des desassembleurs ( envoy� par
CROCONUT ) je sais maintenant ce que fait "Fabrice Bellard" dans
mon fichier VGASTART. Fabrice Bellard est un auteur bien Francais
d'un utilitaire nom� LZEXE qui comprime les fichiers EXE ( comme
EXEPACK de MICROSOFT ) mais avec un rendement bien sup�rieur.
Un fichier comprim� par cet utilitaire est d�comprim� en m�moire
puis execut�. A l'instar de tous les LHARC, PKZIP, LARC etc...
un controle de CRC est fait avant d'executer le fichier. Il est
d�s lors �vident que la moindre modification dans ce fichier fait
tout planter. Cel� explique �galement que la chaine est introuvable
par PCTOOLS puisque cod�e.
Il faut donc que je r�cup�re les utilitaires de BELLARD pour rendre
� ce fichier sa taille originale et pouvoir le modifier.
30 avril 1991
Je viens de r�cup�rer les utilitaires de BELLARD et la modif est
tent�e imm�diatement ...avec succ�s.
Nota: THE STEALTH AFFAIR est �galement "contamin�" par BELLARD ainsi
que beaucoup d'autres, le test le plus simple lors d'un doute c'est
de "donner" l'exe suspect en pature � SOURCER pour avoir confirmation.
11 juin 1991
Ou je me d�cide a attaquer la protection disquette de ce logiciel.
Premi�res remarques: la disquette clef copi�e avec PCTOOLS fonctionne.
Si on copie cette derni�re avec NORTON ou bien DISCOPY du DOS le
programme ne trouve pas la protection.
Je lance QUAID pour savoir ce que fait le programme sur la disquette.
Ce dernier effectue sinplement un test de la place restante � travers
l'INT21 fonction 36 ainsi qu'une op�ration de lecture du fichier
VGASTART.EXE. ( rien d'exceptionnel ) En fait la protection se situe
dans les valeurs que renvoie la fonction 36 de l'INT21.
Dans le fichier VGASTART.EXE on trouve la chaine "A:\VGASTART.EXE",
je remplace A: par C: dans le fichier ( c'est en clair ) et je lance
le jeu.
Ce dernier va toujours lire sur la disquette la place disponible mais,
au retour charge maintenant VGASTART du disque dur.
( c'est d�j� �a... )
Je me penche maintenant sur le moyen de contourner le test de la place
disponible sur la disquette a:.
Il faut qu'au retour de l'INT21 fonction 36 on trouve les valeurs
suivantes dans les registres AX,BX,CX,DX:
AX = 0002
BX = 0000
CX = 0200
DX = 0162
A d�faut le programme attends inlassablement la disquette d'origine
dans le lecteur a:.
L'id�e la plus simple est de modifier le CD21 par un JMP dans une zone
DATA qui place les bonnes valeurs dans les registres puis on revient.
Malheureusement la routine de l'INT21 fonction 36 est cod�e et introu-
vable dans le fichier.
30A8002C1F
CD21 ---> INT 21 ah = 36
CA0600 ---> RETF 0006
0022
A tout hasard j'essaie de voir d'o� provient le CD21 pour �ventuellement
le modifier en CD99 et faire un patch r�sident style STORMLORD ou bien
DICK TRACY. Mais l� encore "ils" ont pens� � tout puisque cette position
est �galement utilis�e ailleurs dans le programme ce qui fait que je me
retrouve avec des INT99 un peu partout.
Je pense � refaire un patch de l'INT40 mais en incr�mentant mon pointeur
de pile je n'arrive pas � retourner dans le CS:IP de mon INT21 !
Apparement on change de SEGMENT SS quelque part.
Il ne reste plus que la solution ultime de d�tourner l'INT21.
C'est extr�mement risqu� puisqu'elle est appel�e constament et que la
sauvegarde et la mise en place des vecteurs d'interruption se font par
l'INT21 elle-m�me !
En principe je laisse �a aux concepteurs de VIRUS ( voir MAGIC VIRUS )
car la moindre erreur au cours de l'installation et le crash est assur�.
Alors je m'y lance malgr� tout pour voir...
En fin de compte cel� fonctionne sans probl�me....et est compl�tement
transparent pour le DOS ainsi que pour la sous-fonction 36 puisqu'au
bout de trois acc�s � cette sous-fonction je r�tablis sa fonction
originelle pour que l'interruption 21 retrouve son int�gralit� pendant
le jeu.
Ayant constat� �galement sur certain type de PC que le jeu se plantait
lorsqu'on relan�ait ce dernier, ( fred2.com s'empile � chaque appel du
jeu ) mais comme il ne grignotait que 600 octets � chaque fois j'ai
laiss� faire. J'y ai donc ajout� une routine qui le d�sinstalle de la
m�moire s'il est appel� une deuxi�me fois.
Ci-dessous le listing de FRED2.COM
; PATCH POUR LE PROGRAMME SAKOBAN II 11 JUIN 1991
; FREDDY_SOFT
; BUT: L'interruption 21 fonction 36 est appel� trois fois de suite
; avec au retour les valeurs suivantes dans les registres:
;
; AX = 0002
; BX = 0000
; CX = 0200
; DX = 0162
;
; afin de faire croire au programme VGASTART.EXE que la protection
; est bien en place...
code segment
org 100h
assume cs:code
start: jmp installe ; On va installer la routine r�sidente...
cr equ 0dh
lf equ 0ah
flag equ 036h
trois equ 3 ; il faut 3 tests de lecture.
initprog db cr,lf
db ' Ce programme fonctionne maintenant sans disque clef...'
db cr,lf
db ' Et sans mot de passe....'
db cr,lf
db ' A une petite fille qui ne pouvait pas lire le code....'
db cr,lf,'$'
instok db cr,lf,' D�tournement de l',39,'INT 21 par FREDDY_SOFT'
db cr,lf
db ' Appuyez sur une touche....','$'
drap db 0,0
compteur db 0,0
elimine db cr,lf,'J',39,'ai en principe tout remis en l',39,'�tat....'
db cr,lf,'$'
int21 label dword ; sauvegarde des adresses SEG:OFF de l'INT21 d'origine
i40off db 0,0 ; OFFSET
i40seg db 0,0 ; SEGMENT
tsrint40 proc far
jmp short apr�s_id
db 'FR' ; On intercalle au d�but du code un identificateur
apr�s_id: sti ; qui permettra de savoir si le programme est l� !
nop
cmp byte ptr [drap],1 ; Si 1 on devient transparent.
jz suite ; Saut � l'INT 21 toutes fonctions valid�es.
cmp ah,flag ; AH = 36.
jnz suite ; Si non on traite les INT 21 normalement.
inc [compteur] ; La protection est test�e 3 fois.
cmp [compteur],trois ; On regarde si elle a �t� test� 3 fois.
jnz encore ; Si non on d�tourne la fonction 36 encore 1 x.
mov drap,1 ; Si oui on met drap = 1.
encore: mov ax,2 ; Si oui on place dans AX,BX,CX et DX les valeurs
xor bx,bx ; attendus par la protection disquette au retour de
mov cx,200h ; l'INT 21 fonction 36. ( get disque space a: ).
mov dx,0162h
jmp fin ; Puis on quitte sans appeler l'INT 21 fonction 36.
suite: pushf ; Pushf et puis un CALL pour appeler l'INT 21 ceci
cli ; pour simuler une instruction INT.
call int21 ; Appel de l'INT21 officielle.
fin: sti
ret 2 ; et on revient
tsrint40 endp
eor:
; ROUTINE D'INSTALLATION
installe: mov ax,3521h
int 21h
cmp word ptr es:[bx+2],'RF' ; On teste la pr�sence de la signature.
je away ; si pr�sent on d�sinstalle.
mov ax,cs ; CS --> DS
mov ds,ax ; DS = CS
mov dx,offset initprog ; pointe sur le message de debut ds:dx.
mov ah,09h ; sous fonction d'affichage.
int 21h ; Affichage.
mov ax,3521h ; on detourne l'int 21h.
int 21h ; sous-fonction 35.
mov word ptr [i40off],bx ; L'offset se retrouve en BX.
mov i40seg,es ; Le segment en ES.
mov ax,2521h ; Et on met l'ad. du resident
mov dx,offset tsrint40 ; sous-fonction 25 dont SEG:OFF se
int 21h ; trouve en DX <---( tsrint40 ).
mov dx,offset instok ; Offset du message de fin.
mov ah,09 ; Sorti du message...
int 21h
mov ah,07 ; Attente d'un caract�re au clavier.
int 21h
mov dx,eor-start+100h+15 ; On r�serve la m�moire qui doit rester
mov cl,4 ; en r�sident: DEBUT code - FIN code +
shr dx,cl ; 100h + 15. ( 100h car un programme COM
mov al,0 ; commence toujours � 100h )
; Puis d�calage de 4 � droite pour avoir
; le r�sultat en nombre de paragraphe
; + 1 ( ou + 15 comme ci-dessus ).
mov ah,31h ; Sortie et reservation
int 21h ; de la m�moire.
away: mov dx,word ptr es:i40off ; Restauration de OFF:SEG de l'INT 21
mov ax,word ptr es:i40seg ; d'origine.
mov ds,ax
mov ax,2521h ; Set vecteur de l' INT 21
int 21h
mov bx,es
mov es,es:[2ch]
mov ah,49h ; On lib�re la m�moire.
int 21h
mov es,bx
mov ah,49h
int 21h
push cs ; Mettre CS dans DS
pop ds
mov dx,offset elimine ; pointe sur d�but du message.
xor al,al
mov ah,9
int 21h ; Sortir message.
mov ah,4ch
int 21h ; On revient au DOS.
code ends
end start
26 Novembre 1991
Ou Mr B m'apprend que ce patch ne fonctionne pas sur un 80486.
Je recharge donc le jeu d'apr�s les disquettes originales car je
n'avais pas sauvegard� les "modifs".
Et je me retrouve �galement avec un programme qui ne fonctionne
plus!. Je passe en revue les modifications �ventuelles depuis le
dernier essai du jeu: je tourne maintenant sur le disque D:
Il faut donc modifier le fichier VGASTART.EXE en cons�quence.
Je pense annuler le nom du drive dans le path de recherche du fichier.
Cel� ne fonctionne pas. Je d�cide d'�crire un programme en C qui
ira tester le lecteur courant et qui modifiera le fichier VGASTART
avant de le lancer.
Le d�tournement d'INT est �galement modifi� en utilisant un programme
PERE qui appelera VGASTART en programme FILS.
Ci-dessous le listing SAKOBAN.C qui modifiera VGASTART.EXE en fonction
du lecteur courant puis le listing de SAKO.ASM qui enl�ve la protection
disquette en rempla�ant le programme FRED2.COM:
************************ SAKOBAN.C *************************
#include
#include
#include
#include /* O_ constant definitions */
#include
#include /* S_ constant definitions */
#include
#include
#include
#include
#include
char inpf[]={"vgastart.exe"};
char car[1];
main()
{
int fh,wrt;
unsigned int dep = 63860; /* a cet endroit se trouve le 'a' de
"a:vgastart.exe" */
char r,p[1];
_clearscreen(_GCLEARSCREEN);
_setbkcolor(rouge);
fentext(15,8,66,14,'�',blanc_brillant);
texte();
cache_curseur();
note(2000,8000);
_setbkcolor(noir);
*p = 97+get_drive(); /* 97 = 'a' */
/* test: printf(" %c ",*p);
*/
chmod(inpf,S_IREAD|S_IWRITE); /* on modifie l'attribut en WRITE */
if((fh=open(inpf,O_BINARY|O_RDWR))==-1)
{
printf("Fichier %s inexistant ou erreur d'ouverture.\n",inpf);
exit(0);
}
lseek(fh,dep,SEEK_SET);
if((wrt=write(fh,p,1))==-1) /* �crit le lecteur courant dans VGASTART.EXE */
printf("erreur d'�criture\n");
close( fh);
}
fentext(x,y,x1,y1,t,c)
int x,y,x1,y1,c;
char unsigned t;
{
int hor,ver,cgb,cdb,cgh,cdh;
int compteur;
_settextcolor(c);
switch(t)
{
case 205:hor=205,ver=186,cgb=201,cdb=187,cgh=200,cdh=188;break;
case 196:hor=196,ver=179,cgb=218,cdb=191,cgh=192,cdh=217;break;
default :hor=ver=cgb=cdb=cgh=cdh=t;
}
_settextposition(y,x);
car[0]=cgb;
_outtext(car);
for(car[0]=hor,compteur=0;compteur-1
|